package comanche.cmd;

import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;


public class CmdFactory {
	
	public static final String DEF_DIR = "/home/loraganna/Desktop/comanche/build/comanche/cmd";
	
	private String dir;
	private HashMap<String,ICmd> cmds;
	private ArrayList<String> names;

	private PlugInLoader loader;

	public CmdFactory() throws MalformedURLException{
		this(DEF_DIR);
	}
	
	private CmdFactory(String dir) throws MalformedURLException {
		super();
		if(!dir.endsWith(File.separator)){
			dir+=File.separator;
		}
		this.dir = dir;
		loader = new PlugInLoader(new URL("file:"+dir));
		cmds = new HashMap<String, ICmd>();
		File root = new File(dir);
		checkForClass(root);
	}

	private String getRelativePath(String path){
		return path.substring(dir.length());
	}

	private void checkForClass(File dir){
		//System.out.println("checking dir : "+dir);
		File[] dirs = dir.listFiles(new DirectoryFilter());
		
		try{
			for(File f : dirs){
				checkForClass(f);
			}
		}catch(NullPointerException npe){}
		File[] classFiles = dir.listFiles(new ClassFilter());
		try{
			for(File f : classFiles){
				processClassFile(f);
			}
		}catch(NullPointerException npe){}
	}

	public String executeAllCommands(File file) {

		Collection<ICmd> c = cmds.values();	
		Iterator<ICmd> itr = c.iterator();
		String temp = "";
	    while(itr.hasNext())
	    {
	    	temp += "<td>" + ((ICmd)itr.next()).process(file) + "</td>";
	    }
	    return temp;
	}
	private void processClassFile(File classFile){
		String className = processPath(classFile);
		try {
			Class<?> command = loadClass(className);
			ICmd c = (ICmd)command.newInstance();//Sert plus a rien, cf newinstance
			cmds.put(c.getName(),c);
		} catch (ClassNotFoundException e) {
			System.out.println("Class Not Found");
		} catch (SecurityException e) {
			System.out.println("Security");
		} catch (IllegalArgumentException e) {
			System.out.println("Wrong Argument");
		} catch (InstantiationException e) {
			System.out.println("Instantiation Exception");
		} catch (IllegalAccessException e) {
			System.out.println("Illegal Access");
		}
	}

	//essaie de Charger la Class dont le nom est en parametre
	private Class<?> loadClass(String className) throws ClassNotFoundException{
		return loader.loadClass(className);
	}


	//Retourne un nom de classe repsectant la hierarchie des packages depuis la racine 
	// exemple : PlugIn/commands/Size.class retourne PlugIn.commands.Size
	private String processPath(File classFile){
		String relpath = getRelativePath(classFile.getPath());
		relpath = relpath.substring(0, relpath.length()-5);
		if(File.separator.equals("\\"))
			relpath = relpath.replaceAll("\\\\","." );
		else
			relpath = relpath.replaceAll(File.separator,".");
		relpath = relpath.substring(0, relpath.length()-1);
		return relpath;
	}
	
	public class DirectoryFilter implements FileFilter {
		public DirectoryFilter() {super();}
		@Override
		public boolean accept(File arg0) {return arg0.isDirectory();}
	}
	
	public class ClassFilter implements FilenameFilter {
		public ClassFilter() {super();}
		@Override
		public boolean accept(File arg0, String arg1) {return arg1.endsWith(".class");}
	}
	
	public class PlugInLoader extends URLClassLoader{ 
		public URL dir;	 
		public PlugInLoader(URL url) {
			super(new URL[0]);
			this.dir = url;
			this.addURL(dir);
		}		 
		public void addDir(String dir){
			try {this.addURL(new URL("file:"+dir));} 
			catch (MalformedURLException e) {	System.out.println("Wrong URL");}
		}
	}
	
	
	
	public HashMap<String, ICmd> getCmds(){
		return this.cmds;
	}
	
	public ArrayList<String> getCmdNames(){
		return this.names;
	}
	
	public ICmd getCmd(String name){
		return cmds.get(name);
	}
	
	/*public static void main (String[] args){
		try {
			CmdFactory c = new CmdFactory();
			for(ICmd cmd : c.getCmds()){
				System.out.println(cmd.process(new File ("/media/data/DownLoads")).get(0));
				
			}
			
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}*/
	

}